package main;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.GregorianCalendar;

/**
 * The main conference class used in Manuview.
 * The conference holds a list of Users and 
 * set deadlines for the conferences submission dates.
 * The conference also holds a list of submitted manuscripts.
 * 
 * Cris added serializable and save functionality.
 * Holly removed deadline array list and added fields for manuscript deadline, 
 * 		 review deadline, and user list. 11/21
 * 
 * @author Cristopher Claeys and Holly Beach
 * @version 12/3
 */
public class Conference implements Serializable {

	/**
	 * Generated serial UID
	 */
	private static final long serialVersionUID = -2742207426962029469L;
	
	private ArrayList<Manuscript> my_manuscripts;	
	private String my_name;
	
	private String my_directory;
	private GregorianCalendar my_manu_deadline;
	private GregorianCalendar my_review_deadline;
	private ArrayList<User>my_users;
		
	/**
	 * Default Constructor 
	 * rev by Holly 11/18 -added my_manuscripts assignment
	 * rev by Holly 11/21 - added my_manu_deadline, my_review_deadline, and my_users assignment.
	 */
	public Conference() {
		my_name = "Default_Name";
		my_manu_deadline = new GregorianCalendar(2011,12,5);
		my_review_deadline = new GregorianCalendar(2012,3,5);
		my_manuscripts = new ArrayList<Manuscript>();
		my_users = new ArrayList<User>();
		my_directory = "";
	}//end of constructor1
	
	
	/**
	 * @author Holly Beach 11/18/11
	 * Holly added parameters and assignments for the 2 deadline fields and list of users
	 * 				and updated preconditions.
	 * Preconditions: a_name must be unique, no other Conference Object exists with a_name
	 * 				  the_manu_deadline >= the current date.
	 * 				  the_review_deadline > the_manu_deadline
	 * 				  the_manuscripts does not contain duplicate manuscript objects.
	 * 				  the_users does not contain duplicate user objects.
	 */
	public Conference(String a_name, GregorianCalendar the_manu_deadline, 
			GregorianCalendar the_review_deadline, ArrayList<Manuscript> the_manuscripts,
			ArrayList<User> the_users) {
		my_name = a_name;
		my_manu_deadline = the_manu_deadline;
		my_review_deadline = the_review_deadline;
		my_manuscripts = the_manuscripts;
		my_users = the_users;
		my_directory = "";
	}//end of constructor2
   
	/**
	 * @return The name of the conference
	 */
	public String getConfName() {
		return my_name;
	}//end of getConfName
	
	/**
	 * @return the submission deadline for manuscripts
	 */
	public GregorianCalendar getManuscriptDeadline() {
		return my_manu_deadline;
	}//end of getManuscriptDeadline
	
	/**
	 * @return the submission deadline for reviews
	 */
	public GregorianCalendar getReviewDeadline() {
		return my_review_deadline;
	}//end of getReviewDeadline
	
	/**
	 * @author Holly 11/18/11
	 * @return list of manuscripts for this conference.
	 * Precondition: The current user role in the GUI must be Roles.PROGRAMCHAIR
	 */
	@SuppressWarnings("unchecked")
	public ArrayList<Manuscript> getManuscripts() {
		return (ArrayList<Manuscript>) my_manuscripts.clone();
	}//end of getManuscripts
	
	/**
	 * @author Holly Beach 11/22/11
	 * @return a list of manuscripts that a_user is the author of, or an empty list if
	 * 			a_user is not an author of any manuscripts in this conference.
	 * 
	 * Precondition: The current user role in the GUI must be Roles.AUTHOR
	 */
	public ArrayList<Manuscript> getManuscriptsForAuthor(User a_user) {
		ArrayList<Manuscript> authored_manuscripts = new ArrayList<Manuscript>();
		for(Manuscript a_manu : my_manuscripts) {
			if (a_manu.getAuthorID().equals(a_user.getID())) {
				authored_manuscripts.add(a_manu);
			}
		}
		return authored_manuscripts;
	}//end of getManuscriptsForAuthor
	
	/**
	 * @author Holly Beach 11/22/11
	 * @return a list of manuscripts that a_user is a reviewer of, or an empty list if
	 * 			a_user is not a reviewer of any manuscripts in this conference.
	 * 
	 * Precondition: The current user role in the GUI must be Roles.REVIEWER
	 */
	public ArrayList<Manuscript> getManuscriptsForReviewer(User a_user) {
		ArrayList<Manuscript> review_manuscripts = new ArrayList<Manuscript>();
		for(Manuscript a_manu : my_manuscripts) {
			for(String revID : a_manu.getReviewers()) {
				if (revID.equals(a_user.getID())){
					review_manuscripts.add(a_manu);
				}
			}
		}
		return review_manuscripts;
	}//end of getManuscriptsForReviewer
	
	/**
	 * @return A list of users in the conference
	 */
	@SuppressWarnings("unchecked")
	public ArrayList<User> getUsers() {
		return (ArrayList<User>) my_users.clone();
	}//end of getUsers
	
	/**
	 * @author Cristopher
	 * 
	 * @return my_directory
	 */
	public String getDirectory() {
		return my_directory;
	}//end of getDirectory

	/**
	 * @author Holly Beach
	 *This method adds a User to the list of users for this conference.
	 *Precondition: getUsers.contains(a_user) == false
	 *Postcondition: getUsers.contains(a_user) == true
	 *				getUsers.size() == old(size) + 1
	 */
	public void addUser(User a_user) {
		my_users.add(a_user);
	}//end of addUser
	
	//TODO adding a manuscript already in conference only 
	//needs to update text? otherwise need _todo_ something
	/**
	 * @author Holly Beach 
	 * Cristopher updated
	 * 
	 * This method adds a manuscript to the list of conference manuscripts.
	 * Postconditions: getManuscripts().contains(a_manuscript) == true.
	 */
	public void addManuscript(Manuscript a_manuscript) {
		int index = my_manuscripts.indexOf(a_manuscript);
		if(index>=0){
			my_manuscripts.get(index).setText(a_manuscript.getText());
		} else{
			my_manuscripts.add(a_manuscript);
		}
	}//end of addManuscript
	
	/**
	 * @author Holly Beach
	 * This method removes a manuscript from the list of conference manuscripts.
	 * Precondition: getManuscripts().contains(a_manuscript) == true.
	 * Postconditions: getManuscripts().contains(a_manuscript) == false.
	 * 				   getManuscripts().size == old(size) - 1
	 */
	public void deleteManuscript(Manuscript a_manuscript) {
		my_manuscripts.remove(a_manuscript);
	}//end of deleteManuscript
	
	//TODO remove this?
	/**
	 * @author Holly Beach
	 * This method removes a_manuscript_old from the list of conference manuscripts and 
	 * adds a_manuscript_new to the list.
	 * Preconditions: getManuscripts().contains(a_manuscript_old) == true.
	 * 				  getManuscripts().contains(a_manuscript_new) == false.
	 * Postconditions: getManuscripts().contains(a_manuscript_new) == true.
	 * 				   getManuscripts().size == old(size)
	 *
	public void updateManuscript(Manuscript a_manuscript_old, 
									Manuscript a_manuscript_new) {
		my_manuscripts.remove(a_manuscript_old);
		my_manuscripts.add(a_manuscript_new);
	}//end of updateManuscript*/
	
	/**
	 * @author Cristopher Claeys
	 * @version 11/27/11
	 * This method adds a_review to the_manu.
	 * Precondition: The conference already contains the specified manuscript
	 * Postconditions: The conference will contain the same manuscripts
	 * 				   The specified manuscript will have one more review than before
	 * 
	 * @param the_manu a manuscript object
	 * @param a_review the new review for the manuscript
	 */
	public void addReview(Manuscript the_manu, Review a_review) {
		the_manu.addReview(a_review);
	}//end of addReview
	
	/**
	 * @author Amandeep Jhajj
	 * updated by Holly, corrected parameters per class diagram.
	 * this methods removes a_review from a manuscript.
	 * Preconditions: getManuscripts.contains(a_manuscript) == true.
	 * 				 a_manuscript.getReviews().contains(a_review) == true.
	 * 
	 * Postconditions: a_manuscript.getReviews().contains(a_review) == false.
	 * @param a_review the review we are attempting to remove.
	 */
	public void deleteReview(Manuscript a_manuscript, Review a_review) {
		a_manuscript.removeReview(a_review);
	}//end deleteReview
	
	/**
	 * @author Holly Beach
	 * This method updates the status of a_manuscript 
	 * with a_status.
	 * Precondition: getManuscripts.contains(a_manuscript) == true
	 * Postcondition: a_manuscript.getStatus() == a_status
	 */
	public void setStatus(Manuscript a_manuscript, 
			Status a_status){
		a_manuscript.setStatus(a_status);
	}//end of setStatus
	
	/**
	 * @author Cristopher
	 * @param the_directory
	 */
	public void setDirectory(String the_directory){
		my_directory = the_directory;
	}//end of setDirectory

	/**
	 * @author Daniel Anderson
	 * This method replaced a review with a 
	 * new updated review.
	 * 
	 * @param a_manuscript a manuscript object
	 * @param a_review an old review object that
	 * will be replaced.
	 * @param a_new_review a new review object
	 */
	public void updateReview(Manuscript a_manuscript, 
			Review a_review, Review a_new_review) {
		if(my_manuscripts.contains(a_manuscript)) {
			a_manuscript.updateReview(a_review, a_new_review);
		}
	}//end of updateReview
	
	/**
	 * @author Cristopher Claeys
	 * This method saves the state of the conference object in a serialized file
	 * Precondition: Write access is available to the directory specified
	 */
	public void save() {
		String filename = my_directory + my_name + ".ser";
		try {
			FileOutputStream fos = new FileOutputStream(filename);
			ObjectOutputStream out = new ObjectOutputStream(fos);
			out.writeObject(this);
			out.close();
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}// end saveData	
}// end Conference class
